/*
* Conditions Of Use
*
* This software was developed by employees of the Sigmatrix(Beijing) Corporation.
* This software is provided by sigmatrix as a service and is expressly
* provided "AS IS."  Sigmatrix MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
* AND DATA ACCURACY.  Sigmatrix does not warrant or make any representations
* regarding the use of the software or the results thereof, including but
* not limited to the correctness, accuracy, reliability or usefulness of
* the software.
*
* Permission to use this software is contingent upon your acceptance
* of the terms of this agreement.
*
*/
package com.sigmatrix.h5.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.sigmatrix.h5.dao.DisRebateAuditDao;
import com.sigmatrix.h5.entity.DisDealer;
import com.sigmatrix.h5.entity.DisDealerAcct;
import com.sigmatrix.h5.entity.DisRebate;
import com.sigmatrix.h5.entity.DisRebateActivity;
import com.sigmatrix.h5.entity.DisRebateAudit;
import com.sigmatrix.h5.enums.CrmAcctType;
import com.sigmatrix.h5.enums.RebateTarget;
import com.sigmatrix.h5.properties.AutoAuditProperties;
import com.sigmatrix.h5.properties.AutoAuditProperties.Module;
import com.sigmatrix.h5.service.DisDealerAcctService;
import com.sigmatrix.h5.service.DisRebateAuditRecordService;
import com.sigmatrix.h5.service.DisRebateAuditService;
import com.sigmatrix.h5.service.DisRebateDetailService;
import com.sigmatrix.h5.service.DisRebateService;
import com.sigmatrix.h5.utils.CommonUtils;
import com.sigmatrix.h5.utils.Constants;
import com.sigmatrix.h5.utils.SessionUtils;
import com.sigmatrix.h5.web.mode.RebateRecord.Rebate;
import com.sigmatrix.h5.web.mode.RebateTotal;
import com.sigmatrix.sc.jdbc.common.service.ServiceImpl;

/**
 *@ClassName: DisRebateAuditServiceImpl
 *@Description: 
 *@author MH
 *@date 2017年8月16日 下午2:04:48
 */
@Service
public class DisRebateAuditServiceImpl extends ServiceImpl<DisRebateAudit,Integer> implements DisRebateAuditService{
	@Autowired
	private DisRebateAuditDao disRebateAuditDao;

	@Autowired
	private DisRebateService disRebateService;
	
	@Autowired(required=false)
	private AutoAuditProperties autoAuditProperties;
	
	@Autowired
	private DisRebateAuditRecordService disRebateAuditRecordService;
	
	@Autowired
	private DisRebateDetailService disRebateDetailService;
	
	@Autowired
	private DisDealerAcctService disDealerAcctService;
	
	@Override
	public List<Rebate> apply(DisRebateActivity activity,Short writeBackDealerLevel,Short promotionCodeType,DisDealer ... dealers) {
		return apply(activity, null, writeBackDealerLevel, null,promotionCodeType,dealers);
	}
	@Override
	@Transactional
	public List<Rebate> apply(DisRebateActivity activity,String source,Short writeBackDealerLevel,String promotionCode,Short promotionCodeType,DisDealer ... dealers) {
		//1.跟返利策略查询各级经销商的返利金额
		Map<String, DisRebate> rebateDetail = disRebateService.judgeRebateAmountOfEachLevel(activity.getStrategyId(),promotionCodeType);
		//判断是否是终端门店扫码(如果门店扫码需要对writeBackDealerLevel+1操作)
		List<Rebate> rebates = new ArrayList<Rebate>();
		if(CrmAcctType.TERMINAL_SHOP.value.equals(SessionUtils.getAcctType())) {
			writeBackDealerLevel ++;
			String key = writeBackDealerLevel+""+RebateTarget.DEALER.value+""+writeBackDealerLevel;
			DisRebate rebate = rebateDetail.get(key);
			if(CommonUtils.isNotEmpty(rebate)){
				Integer auditId = save(activity, null, rebate, SessionUtils.getTerminalShopId(), RebateTarget.TERMINAL_SHOP,writeBackDealerLevel);
				rebates.add(new Rebate(SessionUtils.getTerminalShopId(), RebateTarget.TERMINAL_SHOP.value, rebate.getRebateAmount(),auditId));
			}
		}
		if(CommonUtils.isNotEmpty(dealers)) {
			List<DisDealer> _dealers = Arrays.stream(dealers)
					.sorted((a,b) -> (b.getLevel()==null?0:b.getLevel()) - (a.getLevel()==null?0:a.getLevel()))
					.collect(Collectors.toList());
			//2.根据返利金额发起返利流程
			Integer salesManId = null;
			if(CommonUtils.isNotEmpty(promotionCode)){
				DisDealerAcct _acct = disDealerAcctService.findByPromotionCode(promotionCode);
				if(CommonUtils.isNotEmpty(_acct))salesManId = _acct.getId();
			}
			//给经销商业务员返利
			for (DisDealer dealer : _dealers) {
				rebateForDealer(rebates, activity, source, writeBackDealerLevel, rebateDetail, dealer);
				if(CommonUtils.isEmpty(salesManId)){
					salesManId = dealer.getDealersAcctId();
				}
				if(CommonUtils.isNotEmpty(salesManId)){
					rebateForSalesMan(rebates, activity, source, writeBackDealerLevel, rebateDetail, dealer.getLevel(),salesManId);
					DisDealerAcct acct = disDealerAcctService.findSalesMan(salesManId);
					if(CommonUtils.isNotEmpty(acct)){
						salesManId = acct.getId();
					}else{
						salesManId = null;
					}
				}
			}
			//给企业业务员返利
			if(CommonUtils.isNotEmpty(salesManId) )
				rebateForSalesMan(rebates, activity, source, writeBackDealerLevel, rebateDetail, Short.valueOf("0"),salesManId);
		}
		return rebates;
	}
	
	private void rebateForDealer(List<Rebate> rebates,DisRebateActivity activity,String source,Short writeBackDealerLevel,Map<String,DisRebate> rebateDetail,DisDealer dealer){
		String dealerKey = writeBackDealerLevel+""+RebateTarget.DEALER.value+""+dealer.getLevel();
		if (rebateDetail.containsKey(dealerKey)) {
			DisRebate rebate = rebateDetail.get(dealerKey);
			if(CommonUtils.isNotEmpty(rebate)){
				Integer rebateId = save(activity,source, rebate, dealer.getId(),RebateTarget.DEALER,dealer.getLevel());
				rebates.add(new Rebate(dealer.getId(), RebateTarget.DEALER.value, rebate.getRebateAmount(),rebateId));
			}
		}
	}
	private void rebateForSalesMan(List<Rebate> rebates,DisRebateActivity activity,String source,Short writeBackDealerLevel,Map<String,DisRebate> rebateDetail,Short rebateLevel,Integer salesManId){
		String salesManKey = writeBackDealerLevel+""+RebateTarget.SALES_MAN.value+""+rebateLevel;
		DisRebate rebate = rebateDetail.get(salesManKey);
		if(CommonUtils.isNotEmpty(rebate)){
			Integer auditId = save(activity,source, rebate, salesManId,RebateTarget.SALES_MAN,rebateLevel);
			rebates.add(new Rebate(salesManId, RebateTarget.SALES_MAN.value, rebate.getRebateAmount(),auditId));
		}
	}
	private Integer save(DisRebateActivity activity,String source,DisRebate rebate,Integer dealerId,RebateTarget rebateTarget,Short dealerLevel){
		boolean auto = CommonUtils.isNotEmpty(autoAuditProperties) && autoAuditProperties.auto(SessionUtils.getEseCode(), Module.rebate);
		DisRebateAudit audit = new DisRebateAudit();
		audit.setSource(source);
		audit.setAmount(rebate.getRebateAmount());
		audit.setDealerId(dealerId);
		audit.setStartTime(activity.getStartTime());
		audit.setEndTime(activity.getEndTime());
		audit.setStrategyId(activity.getStrategyId());
		audit.setRebateActivityId(activity.getId());
		audit.setStatus(Constants.STATUS_ENABLE);
		audit.setCreateTime(new Date());
		audit.setDealerType(rebateTarget.value);
		audit.setDealerLevel(dealerLevel);
		Integer id = insertSelective(audit);
		if(auto){
			//ThreadPool.submit(Void ->{
				disRebateAuditRecordService.save(audit);
				disRebateDetailService.save(audit);
			//});
		}
		return id;
	}
	@Override
	public RebateTotal statisticByDealerAndActivity(Integer dealerId, Short dealerType, Integer activityId) {
		return disRebateAuditDao.statisticByDealerAndActivity(dealerId, dealerType, activityId);
	}
}
